import greenfoot.*;
import java.util.ArrayList;
/**
 *  贪食蛇类，用来控制蛇头移动，获取食物，并对蛇身进行管理
 */
public class Snake extends Actor{
    private ArrayList<Body> body;             //body列表用来保存蛇身
    protected int length;                       //蛇身长度
    protected int speed;                        //蛇头移动速度
    protected int direction;                    //蛇头移动方向
    public static final int SOUTH = 0;        //该常量代表向下移动
    public static final int NORTH = 1;        //该常量代表向上移动
    public static final int EAST = 2;         //该常量代表向右移动
    public static final int WEST = 3;         //该常量代表向左移动
    public World myWorld;
    
    protected int setSpeed = 40;  // 设定速度
    protected int originalSpeed = 30;  // 初始速度
    protected long startTime = 0;  // 计时器起始时间
    protected long duration = 5000;  // 倒计时3秒（3000毫秒）
    //构造方法，初始化基本字段值
    public Snake(World _myWorld) {   
        body = new ArrayList<Body>();
        length = 1;
        speed = getImage().getAwtImage().getWidth()+2;
        myWorld = _myWorld;
    }

    //处理游戏逻辑
    public void act() {
        checkKeydown();
        move();
        updateBody();
        checkFood();
        checkEdge();
        checkGameOver();
        
        checkTime();
    } 

    //检查是否获取食物
    public void checkFood(){
        if(isTouching(Food.class)){  //若蛇头碰到食物，且蛇身未达到上限，则
            length++;                                 //蛇身长度增加一个单位
        }
        if(isTouching(Food0.class)){
             // 启动计时器，修改速度
            startTime = System.currentTimeMillis();
            Greenfoot.setSpeed(setSpeed);
        }
    }

    //更新贪食蛇身体
    public void updateBody(){
        if (length > 1) {
            if(body.size()==length){
                body.remove(0);     //从蛇身列表中移除蛇尾对应的Body对象
            }
            World w=getWorld();
            w.removeObjects(w.getObjects(Body.class));  //将蛇身从游戏世界中移除
            for(Body b:body){      //根据蛇身各部分的位置重新添加至游戏世界
                w.addObject(b, b.getLocX(),b.getLocY());
            }
            body.add(new Body(getX(),getY()));  //将蛇头对应的Body对象添加至蛇身列表
        }
    }
    
    //控制蛇头朝不同方向移动
    public void move(){
        switch (direction) {
            case SOUTH:
            setLocation(getX(), getY()+speed);
            break;
            case NORTH:
            setLocation(getX(), getY()-speed);
            break;
            case EAST:
            setLocation(getX()+speed, getY());
            break;
            case WEST:
            setLocation(getX()-speed, getY());
            break;
        }           
    }

    //检查游戏是否结束
    public void checkGameOver(){
       if(isTouching(Body.class)||isTouching(Food3.class)||isTouching(Block.class)){  //若蛇头碰到窗口边界或是蛇身，则
            Greenfoot.setWorld(new GameOverMenu("玩家",getLength()-1,-1));
        }
    }
    public void checkEdge()
    {
        if(getX()>myWorld.getWidth()-2)
        {
            setLocation(-1, getY());
        }
        else if(getX()<2)
        {
            setLocation(myWorld.getWidth()-2, getY());
        }
        else if(getY()>myWorld.getHeight()-2)
        {
            setLocation(getX(), -1);
        }
        else if(getY()<2)
        {
            setLocation(getX(), myWorld.getHeight()-2);
        }
        
    }

    //检测键盘按键事件，若按下方向键，则分别控制贪食蛇朝相应方向移动
    public void checkKeydown(){
        if(Greenfoot.isKeyDown("up")&&direction!=SOUTH){
            direction=NORTH;
        }
        else  if(Greenfoot.isKeyDown("down")&&direction!=NORTH){
            direction=SOUTH;
        }
        else  if(Greenfoot.isKeyDown("left")&&direction!=EAST){
            direction=WEST;
        }
        else  if(Greenfoot.isKeyDown("right")&&direction!=WEST){
            direction=EAST;
        }

    }
    public void plusLength(int addedLength)
    {
        length+=addedLength;
    }
    public void checkTime()
    {
        if (startTime != 0 && System.currentTimeMillis() - startTime > duration) {
            // 如果计时结束，恢复原来的速度
            Greenfoot.setSpeed(originalSpeed);
            startTime = 0;  // 重置计时器
        }
    }
    public int getLength()
    {
        return length;
    }
    public boolean isTouchingDoor()
    {
        if(isTouching(Door.class))
        return true;
        else
        return false;
    }
}
